#pragma once
#include <iostream>
#include <assert.h>
#include "vectorExpr.h"
/*
CRTP（Curiously Recurring Template Pattern）用于在基类中调用派生类的方法，实现统一接口
操作符重载 	返回表达式对象而非直接计算结果
延迟求值 	在赋值时才执行完整表达式计算
无临时对象 	避免多次分配和释放内存
*/
namespace math
{
	// 表示二维向量，Vector2[0]=x,Vector2[1] =y,向量(x,y)表示点（0,0）到点（x,y）的距离和方向
	template <typename T, std::size_t N>
	class Vector : public VectorExpr<Vector<T, N>, T, N>
	{
	private:
		std::array<T, N> data;

	public:
		Vector() = default;
		Vector(std::initializer_list<T> init)
		{
			if (init.size() != N)
			{
				throw std::invalid_argument("Initializer list size mismatch");
			}
			std::copy(init.begin(), init.end(), data.begin());
			
		}
		T &operator[](size_t i) { return data[i]; }
		T operator[](size_t i) const { return data[i]; }
		T &operator()(size_t i) { return data[i]; }
		T operator()(size_t i) const { return data[i]; }

		template <typename Expr>
		Vector &operator=(const VectorExpr<Expr, T, N> &expr)
		{
			for (std::size_t i = 0; i < N; ++i)
			{
				data[i] = expr(i);
			}
			return *this;
		}

		Vector<T, N> operator*(T f) const
		{
			Vector<T, N> v;
			for (std::size_t i = 0; i < N; ++i)
			{
				v.data[i] = data[i] * f;
			}
			return v;
		}

		// 用于计算向量归一化
		Vector<T, N> operator/(T f) const
		{
			assert(f != 0);
			float inv = static_cast<T>(1) / f;
			Vector<T, N> v;
			for (std::size_t i = 0; i < N; ++i)
			{
				v.data[i] = data[i] * inv;
			}
			return v;
		}

		void printf()
		{
			for (int i = 0; i < N; i++)
			{
				std::cout << data[i] << " ";
			}
			std::cout<<"\n";
		}
	};
	using vec2f = Vector<float, 2>;
	using vec2i = Vector<int, 2>;
	using vec3f = Vector<float, 3>;
	using vec3i = Vector<int, 3>;
	using vec4f = Vector<float, 4>;
	using vec4i = Vector<int, 4>;
}
